package webdriver.elements;

import java.util.List;
import java.util.Random;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;

/**
 * Класс, описывающий комбобокс (выпадающий список)
 */
public class ComboBox extends BaseElement {

	/**
	 * Конструктор
	 * @param locator locator
	 * @param name name
	 */
	public ComboBox(final By locator, final String name) {
		super(locator, name);
	}
	   /**
     * getElementType
     * @return Комбобокс
     */
	protected String getElementType() {
		return "Комбобокс";
	}

	/**
	 * Конструктор с подстановкой в xpathLocatorTemplate значения locatorValue
	 * @param xpathLocatorTemplate шаблон локатора
	 * @param locatorValue значение
	 * @param nameOf название элемента
	 */
	public ComboBox(String xpathLocatorTemplate, String locatorValue, String nameOf) {
		super(xpathLocatorTemplate, locatorValue, nameOf);
	}

	/**
	 * Выбрать значение из списка
	 * @param optionLocator Локатор значения, которое необходимо выбрать
	 */
	public void select(String optionLocator) {
		waitAndAssertIsPresent();
		info(String.format("Выбрираемое значение '%1$s'", optionLocator));
		new Select(element).selectByVisibleText(optionLocator);
	}

	/**
	 * selectByText
	 * @param value value
	 */
	public void selectByText(String value) {
		waitAndAssertIsPresent();
		info(String.format("Выбрираемое значение '%1$s'", value));
		new Select(element).selectByVisibleText(value);
	}

	/**
	 * selectByValue
	 * @param value value
	 */
	public void selectByValue(String value) {
		waitAndAssertIsPresent();
		info(String.format("Выбрираемое значение '%1$s'", value));
		new Select(element).selectByValue(value);
	}

	/**
	 * getSelectedText
	 * @return selectedText
	 */
	public String getSelectedText() {
		waitAndAssertIsPresent();
		return (new Select(element)).getFirstSelectedOption().getText();
	}

	/** Выбирает первое доступное значение из комбобокса
	 * @return выбранное значение
	 */
	public String selectRandomByText(){
		String text = "";
		waitAndAssertIsPresent();
		Select select = new Select(element);
		List<WebElement> options = select.getOptions();
		// Проверка, что выпадающий список не пуст
		if(options.size() == 1 && (options.get(0).getText().equals("") || options.get(0).getText().equals("Не выбрано"))){
			fatal("Выпадающий список пуст!");
		}else if(options.size() == 1){
			text = options.get(0).getText();
		}else{
			int index = new Random().nextInt(options.size() - 1) + 1;
			text = options.get(index).getText();
		}
		info("Выбираемое значение из выпадающего списка: '" +  text + "'");
		select.selectByVisibleText(text);
		return text;
	}

	/** Выбирает случайное значение из комбобокса
	 * @return value выбранного значения
	 */
	public String selectRandomByValue(){
		String value = "";
		waitAndAssertIsPresent();
		Select select = new Select(element);
		List<WebElement> options = select.getOptions();
		// Проверка, что выпадающий список не пуст
		if(options.size() == 1 && (options.get(0).getAttribute("value").equals(""))){
			fatal("Выпадающий список пуст!");
		}else if(options.size() == 1){
			value = options.get(0).getAttribute("value");
		}else{
			int index = new Random().nextInt(options.size() - 1) + 1;
			value = options.get(index).getAttribute("value");
		}
		info("Выбираемое значение из выпадающего списка value = '" +  value + "'");
		selectByValue(value);
		return value;
	}

	/** Выбирает значение из списка по аттрибуту label
	 * @param label значение аттрибута label
	 */
	public void selectByLabel(String label){
		String value = null;
		waitAndAssertIsPresent();
		Select select = new Select(element);
		List<WebElement> options = select.getOptions();
		for(int i = 0; i < options.size(); i++){
			if(options.get(i).getAttribute("label").equals(label)){
				value = options.get(i).getAttribute("value");
				info("Выбираемое значение из выпадающего списка value = '" +  value + "'");
				selectByValue(value);
				return;
			}
		}
		logger.fatal("В комбобоксе нету элемента со значением аттрибута label равным '" + label + "'");
	}

	/** Select value from cmb by some part of option's attribute
	 * @param attribute attribute of option element
	 * @param value some part value of attribute
	 */
	public void selectByAttributeContains(String attribute, String value){
		waitAndAssertIsPresent();
		Select select = new Select(element);
		List<WebElement> options = select.getOptions();
		for(int i = 0; i < options.size(); i++){
			if(options.get(i).getAttribute(attribute).contains(value)){
				value = options.get(i).getAttribute("value");
				info("Выбираемое значение из выпадающего списка value = '" +  value + "'");
				selectByValue(value);
				selectByText(value);
				return;
			}
		}
		logger.fatal("В комбобоксе нету элемента со значением аттрибута " + attribute + " равным '" + value + "'");
	}

	/** Select value from cmb by some part of option's text
	 * @param text some part of option's text
	 */
	public void selectByTextContains(String text){
		waitAndAssertIsPresent();
		Select select = new Select(element);
		List<WebElement> options = select.getOptions();
		for(int i = 0; i < options.size(); i++){
			if(options.get(i).getText().contains(text)){
				text = options.get(i).getText();
				info("Выбираемое значение из выпадающего списка text = '" +  text + "'");
				selectByText(text);
				return;
			}
		}
		logger.fatal("В комбобоксе нету элемента с текстом равным '" + text + "'");
	}
}
